﻿// MFCApplication2View.cpp: CMFCApplication2View 类的实现
//

#include "pch.h"
#include "framework.h"
// SHARED_HANDLERS 可以在实现预览、缩略图和搜索筛选器句柄的
// ATL 项目中进行定义，并允许与该项目共享文档代码。
#ifndef SHARED_HANDLERS
#include "MFCApplication2.h"
#endif

#include "MFCApplication2Doc.h"
#include "MFCApplication2View.h"

// CMFCApplication2View

IMPLEMENT_DYNCREATE(CMFCApplication2View, CView)

BEGIN_MESSAGE_MAP(CMFCApplication2View, CView)
	ON_WM_SIZE()
	ON_WM_MOUSEMOVE()
	ON_WM_MOUSEWHEEL()
	ON_WM_MOUSELEAVE()
	ON_WM_NCMOUSEMOVE()
	ON_WM_LBUTTONDOWN()
	ON_WM_LBUTTONUP()
	ON_WM_MBUTTONDOWN()
	ON_WM_MBUTTONUP()
	ON_WM_RBUTTONDOWN()
	ON_WM_RBUTTONUP()

	// 标准打印命令
	ON_COMMAND(ID_FILE_PRINT, &CView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_DIRECT, &CView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_PREVIEW, &CView::OnFilePrintPreview)
	ON_COMMAND(ID_VIEW_FRONT, &CMFCApplication2View::OnViewFront)
	ON_COMMAND(ID_VIEW_TOP, &CMFCApplication2View::OnViewTop)
	ON_COMMAND(ID_CAD_IMPORT, &CMFCApplication2View::OnCadImport)
	ON_COMMAND(ID_SELECTION_FACE, &CMFCApplication2View::OnSelectionFace)
END_MESSAGE_MAP()

// CMFCApplication2View 构造/析构

CMFCApplication2View::CMFCApplication2View() noexcept
	: myUpdateRequests(0),
	myCurZoom(0.0),
	myCurrentMode(CurAction3d_Nothing)
{
	myDefaultGestures = myMouseGestureMap;
}

CMFCApplication2View::~CMFCApplication2View()
{
}

BOOL CMFCApplication2View::PreCreateWindow(CREATESTRUCT& cs)
{
	// TODO: 在此处通过修改
	//  CREATESTRUCT cs 来修改窗口类或样式

	return CView::PreCreateWindow(cs);
}

// CMFCApplication2View 绘图

void CMFCApplication2View::OnDraw(CDC* /*pDC*/)
{
	CMFCApplication2Doc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;

	myView->InvalidateImmediate();
	FlushViewEvents(GetDocument()->GetContext(), myView, true);
}

// CMFCApplication2View 打印

BOOL CMFCApplication2View::OnPreparePrinting(CPrintInfo* pInfo)
{
	// 默认准备
	return DoPreparePrinting(pInfo);
}

void CMFCApplication2View::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: 添加额外的打印前进行的初始化过程
}

void CMFCApplication2View::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: 添加打印后进行的清理过程
}

// CMFCApplication2View 诊断

#ifdef _DEBUG
void CMFCApplication2View::AssertValid() const
{
	CView::AssertValid();
}

void CMFCApplication2View::Dump(CDumpContext& dc) const
{
	CView::Dump(dc);
}

CMFCApplication2Doc* CMFCApplication2View::GetDocument() const // 非调试版本是内联的
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMFCApplication2Doc)));
	return (CMFCApplication2Doc*)m_pDocument;
}
#endif //_DEBUG

// CMFCApplication2View 消息处理程序

void CMFCApplication2View::OnInitialUpdate()

{
	CView::OnInitialUpdate();

	myView = GetDocument()->GetViewer()->CreateView();
	myView->SetShadingModel(V3d_GOURAUD);
	Handle(Graphic3d_GraphicDriver) theGraphicDriver = ((CMFCApplication2App*)AfxGetApp())->GetGraphicDriver();
	Aspect_Handle aWindowHandle = (Aspect_Handle)GetSafeHwnd();
	Handle(WNT_Window) aWntWindow = new WNT_Window(GetSafeHwnd());
	myView->SetWindow(aWntWindow);
	if (!aWntWindow->IsMapped()) {
		aWntWindow->Map();
	}
	Standard_Integer w = 100;
	Standard_Integer h = 100;
	aWntWindow->Size(w, h);
	::PostMessage(GetSafeHwnd(), WM_SIZE, SIZE_RESTORED, w + h * 65536);
	myView->FitAll();

	myView->ZBufferTriedronSetup(Quantity_NOC_RED, Quantity_NOC_GREEN, Quantity_NOC_BLUE1, 0.8, 0.05, 12);
	myView->TriedronDisplay(Aspect_TOTP_LEFT_LOWER, Quantity_NOC_WHITE, 0.2, V3d_ZBUFFER);
}

void CMFCApplication2View::OnViewFront()
{
	myView->SetProj(V3d_Xneg);
	myView->FitAll();
}

void CMFCApplication2View::OnViewTop()
{
	myView->SetProj(V3d_Zneg);
	myView->FitAll();
}

// =======================================================================
// function : defineMouseGestures
// purpose  :
// =======================================================================
void CMFCApplication2View::defineMouseGestures()
{
	myMouseGestureMap.Clear();
	AIS_MouseGesture aRot = AIS_MouseGesture_RotateOrbit;
	switch (myCurrentMode)
	{
	case CurAction3d_Nothing:
	{
		myMouseGestureMap = myDefaultGestures;
		break;
	}
	case CurAction3d_DynamicZooming:
	{
		myMouseGestureMap.Bind(Aspect_VKeyMouse_LeftButton, AIS_MouseGesture_Zoom);
		break;
	}
	case CurAction3d_GlobalPanning:
	{
		break;
	}
	case CurAction3d_WindowZooming:
	{
		myMouseGestureMap.Bind(Aspect_VKeyMouse_LeftButton, AIS_MouseGesture_ZoomWindow);
		break;
	}
	case CurAction3d_DynamicPanning:
	{
		myMouseGestureMap.Bind(Aspect_VKeyMouse_LeftButton, AIS_MouseGesture_Pan);
		break;
	}
	case CurAction3d_DynamicRotation:
	{
		myMouseGestureMap.Bind(Aspect_VKeyMouse_LeftButton, aRot);
		break;
	}
	}
}

// =======================================================================
// function : OnMouseMove
// purpose  :
// =======================================================================
void CMFCApplication2View::OnMouseMove(UINT theFlags, CPoint thePoint)
{
	TRACKMOUSEEVENT aMouseEvent;          // for WM_MOUSELEAVE
	aMouseEvent.cbSize = sizeof(aMouseEvent);
	aMouseEvent.dwFlags = TME_LEAVE;
	aMouseEvent.hwndTrack = m_hWnd;
	aMouseEvent.dwHoverTime = HOVER_DEFAULT;
	if (!::_TrackMouseEvent(&aMouseEvent)) { TRACE("Track ERROR!\n"); }

	const Aspect_VKeyFlags aFlags = WNT_Window::MouseKeyFlagsFromEvent(theFlags);
	if (UpdateMousePosition(Graphic3d_Vec2i(thePoint.x, thePoint.y), PressedMouseButtons(), aFlags, false))
	{
		update3dView();
	}
}

#include "ShapeAnalysis_ShapeContents.hxx"
void ShapeContent(const TopoDS_Shape& shape)
{
	//GREEN("[ShapeContent]");

	ShapeAnalysis_ShapeContents ana;
	ana.Perform(shape);

	printf("Num of Solid: %d \n ", ana.NbSolids());
	printf("Num of Shell: %d\n ", ana.NbShells());
	printf("Num of Face: %d\n", ana.NbFaces());
	printf("Num of Wire: %d\n", ana.NbWires());
	printf("Num of Edge: %d\n", ana.NbEdges());
	printf("Num of Vertex: %d\n", ana.NbVertices());
	printf("Num of BSpline Surf:%d \n", ana.NbBSplibeSurf());
	printf("Num of Bezier Surf:%d \n", ana.NbBezierSurf());
	printf("Num of Free faces: %d\n", ana.NbFreeFaces());
	printf("Num of Free wires: %d\n", ana.NbFreeWires());
	printf("Num of Free edges: %d\n", ana.NbFreeEdges());
	printf("Num of Shared wires: %d\n", ana.NbSharedWires());
	printf("Num of Shared edges: %d \n", ana.NbSharedEdges());
}

// =======================================================================
// function : OnLButtonDown
// purpose  :
// =======================================================================
void CMFCApplication2View::OnLButtonDown(UINT theFlags, CPoint thePoint)
{
	const Aspect_VKeyFlags aFlags = WNT_Window::MouseKeyFlagsFromEvent(theFlags);
	PressMouseButton(Graphic3d_Vec2i(thePoint.x, thePoint.y), Aspect_VKeyMouse_LeftButton, aFlags, false);

	Handle(AIS_InteractiveContext) theCtx = GetDocument()->GetContext();
	theCtx->MoveTo(thePoint.x, thePoint.y, myView, Standard_False);
	//	theCtx->Select(Standard_True);
	theCtx->SelectDetected(AIS_SelectionScheme_Replace);

	theCtx->InitSelected();

	if (theCtx->NbSelected() == 1) {
		TopoDS_Shape shape = theCtx->SelectedShape();
		TopoDS_Face aFace = TopoDS::Face(shape);

		//aFace.DumpJson(std::cout);
		ShapeContent(aFace);
	}

	update3dView();
}

// =======================================================================
// function : OnLButtonUp
// purpose  :
// =======================================================================
void CMFCApplication2View::OnLButtonUp(UINT theFlags, CPoint thePoint)
{
	const Aspect_VKeyFlags aFlags = WNT_Window::MouseKeyFlagsFromEvent(theFlags);
	ReleaseMouseButton(Graphic3d_Vec2i(thePoint.x, thePoint.y), Aspect_VKeyMouse_LeftButton, aFlags, false);
	if (myCurrentMode == CurAction3d_GlobalPanning)
	{
		myView->Place(thePoint.x, thePoint.y, myCurZoom);
		myView->Invalidate();
	}
	if (myCurrentMode != CurAction3d_Nothing)
	{
		setCurrentAction(CurAction3d_Nothing);
	}
	update3dView();
}

// =======================================================================
// function : OnMButtonDown
// purpose  :
// =======================================================================
void CMFCApplication2View::OnMButtonDown(UINT theFlags, CPoint thePoint)
{
	const Aspect_VKeyFlags aFlags = WNT_Window::MouseKeyFlagsFromEvent(theFlags);
	PressMouseButton(Graphic3d_Vec2i(thePoint.x, thePoint.y), Aspect_VKeyMouse_MiddleButton, aFlags, false);
	update3dView();
}

// =======================================================================
// function : OnMButtonUp
// purpose  :
// =======================================================================
void CMFCApplication2View::OnMButtonUp(UINT theFlags, CPoint thePoint)
{
	const Aspect_VKeyFlags aFlags = WNT_Window::MouseKeyFlagsFromEvent(theFlags);
	ReleaseMouseButton(Graphic3d_Vec2i(thePoint.x, thePoint.y), Aspect_VKeyMouse_MiddleButton, aFlags, false);
	update3dView();
	if (myCurrentMode != CurAction3d_Nothing)
	{
		setCurrentAction(CurAction3d_Nothing);
	}
}

// =======================================================================
// function : OnRButtonDown
// purpose  :
// =======================================================================
void CMFCApplication2View::OnRButtonDown(UINT theFlags, CPoint thePoint)
{
	const Aspect_VKeyFlags aFlags = WNT_Window::MouseKeyFlagsFromEvent(theFlags);
	PressMouseButton(Graphic3d_Vec2i(thePoint.x, thePoint.y), Aspect_VKeyMouse_RightButton, aFlags, false);
	update3dView();
	myClickPos.SetValues(thePoint.x, thePoint.y);
}

// =======================================================================
// function : OnRButtonUp
// purpose  :
// =======================================================================
void CMFCApplication2View::OnRButtonUp(UINT theFlags, CPoint thePoint)
{
	const Aspect_VKeyFlags aFlags = WNT_Window::MouseKeyFlagsFromEvent(theFlags);
	ReleaseMouseButton(Graphic3d_Vec2i(thePoint.x, thePoint.y), Aspect_VKeyMouse_RightButton, aFlags, false);
	update3dView();
	if (myCurrentMode != CurAction3d_Nothing)
	{
		setCurrentAction(CurAction3d_Nothing);
	}
}

// =======================================================================
// function : OnMouseWheel
// purpose  :
// =======================================================================
BOOL CMFCApplication2View::OnMouseWheel(UINT theFlags, short theDelta, CPoint thePoint)
{
	const Standard_Real aDeltaF = Standard_Real(theDelta) / Standard_Real(WHEEL_DELTA);
	CPoint aCursorPnt = thePoint;
	ScreenToClient(&aCursorPnt);
	const Graphic3d_Vec2i  aPos(aCursorPnt.x, aCursorPnt.y);
	const Aspect_VKeyFlags aFlags = WNT_Window::MouseKeyFlagsFromEvent(theFlags);
	if (UpdateMouseScroll(Aspect_ScrollDelta(aPos, aDeltaF, aFlags)))
	{
		update3dView();
	}
	return true;
}

// =======================================================================
// function : OnSize
// purpose  :
// =======================================================================
void CMFCApplication2View::OnSize(UINT nType, int cx, int cy)
{
	CView::OnSize(nType, cx, cy);
	if (cx != 0
		&& cy != 0
		&& !myView.IsNull())
	{
		myView->Window()->DoResize();
		myView->MustBeResized();
		myView->Invalidate();
		update3dView();
	}
}

// =======================================================================
// function : OnMouseLeave
// purpose  :
// =======================================================================
void CMFCApplication2View::OnMouseLeave()
{
	CPoint aCursorPos;
	if (GetCursorPos(&aCursorPos))
	{
		ReleaseMouseButton(Graphic3d_Vec2i(aCursorPos.x, aCursorPos.y),
			PressedMouseButtons(),
			Aspect_VKeyMouse_NONE,
			false);
	}
}

void CMFCApplication2View::handleViewRedraw(const Handle(AIS_InteractiveContext)& theCtx,
	const Handle(V3d_View)& theView)
{
	myUpdateRequests = 0;
	AIS_ViewController::handleViewRedraw(theCtx, theView);
}

// ================================================================
// Function : update3dView
// Purpose  :
// ================================================================
void CMFCApplication2View::update3dView()
{
	if (!myView.IsNull())
	{
		if (++myUpdateRequests == 1)
		{
			Invalidate(FALSE);
			UpdateWindow();
		}
	}
}

#include "TDocStd_Application.hxx"
#include "XCAFApp_Application.hxx"
#include "STEPCAFControl_Reader.hxx"
#include "XCAFDoc_DocumentTool.hxx"
#include "XCAFPrs_AISObject.hxx"
#include "TDF_LabelSequence.hxx"
#include "XCAFDoc_ShapeTool.hxx"
void CMFCApplication2View::OnCadImport()
{
	CFileDialog dlg(TRUE);
	if (dlg.DoModal() != IDOK)
		return;

	Handle(TDocStd_Application) aTmpApplication = XCAFApp_Application::GetApplication();
	STEPCAFControl_Reader aStepReader;

	const TCollection_AsciiString aStr(dlg.GetPathName());
	IFSelect_ReturnStatus aStatus = aStepReader.ReadFile(aStr.ToCString());
	if (aStatus != IFSelect_RetDone)
		return;

	aStepReader.SetColorMode(Standard_True);
	aStepReader.SetLayerMode(Standard_True);
	aStepReader.SetNameMode(Standard_True);

	Handle(TDocStd_Document) aDocument;
	aTmpApplication->NewDocument("BinOcaf", aDocument);
	if (Standard_False == aStepReader.Transfer(aDocument) ? aTmpApplication : Handle(TDocStd_Application)())
		return;

	TDF_Label mainLabel = aDocument->Main();
	Handle(XCAFDoc_ShapeTool) myShapeTool = XCAFDoc_DocumentTool::ShapeTool(mainLabel);
	Handle(XCAFDoc_ColorTool) myColors = XCAFDoc_DocumentTool::ColorTool(mainLabel);

	TDF_LabelSequence FreeShape;
	myShapeTool->GetFreeShapes(FreeShape);
	for (auto label : FreeShape)
	{
		Handle(XCAFPrs_AISObject) theShape = new XCAFPrs_AISObject(label);
		theShape->SetDisplayMode(AIS_Shaded);

		GetDocument()->GetContext()->Display(theShape, true);
	}
}

#include "Prs3d_Drawer.hxx"
void CMFCApplication2View::OnSelectionFace()
{
	Handle(AIS_InteractiveContext) theCtx = GetDocument()->GetContext();

	theCtx->Deactivate();
	theCtx->Activate(AIS_Shape::SelectionMode(TopAbs_FACE));

	Handle(Prs3d_Drawer) aDrawer = theCtx->HighlightStyle();
	aDrawer->SetMethod(Aspect_TOHM_COLOR);
	aDrawer->SetColor(Quantity_NOC_RED);
	aDrawer->SetDisplayMode(AIS_Shaded);
	theCtx->SetHighlightStyle(Prs3d_TypeOfHighlight_LocalDynamic, aDrawer);
	theCtx->SetAutomaticHilight(Standard_True);
}